#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
飞书授权回调服务器
用于处理飞书OAuth授权回调，显示美观的静态页面并提取授权码
"""

import os
import sys
import json
import time
import threading
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
from socketserver import ThreadingMixIn

# 添加src目录到Python路径
sys.path.insert(0, os.path.dirname(__file__))

try:
    from config import Config
    from feishu_bitable_client import FeishuBitableClient
except ImportError as e:
    print(f"❌ 导入失败: {e}")
    print("请确保在项目根目录运行此脚本")
    sys.exit(1)


class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
    """支持多线程的HTTP服务器"""
    daemon_threads = True
    allow_reuse_address = True


class FallbackHandler(BaseHTTPRequestHandler):
    """处理飞书授权回调的HTTP请求处理器"""
    
    # 类变量，用于存储授权码和状态
    auth_code = None
    auth_state = None
    server_should_stop = False
    
    def load_html_template(self, template_name, **kwargs):
        """加载HTML模板文件并替换占位符
        
        Args:
            template_name: 模板文件名（不含扩展名）
            **kwargs: 要替换的占位符键值对
        
        Returns:
            str: 处理后的HTML内容
        """
        try:
            # 获取模板文件路径
            template_dir = os.path.join(os.path.dirname(__file__), 'templates')
            template_path = os.path.join(template_dir, f'{template_name}.html')
            
            # 读取模板文件
            with open(template_path, 'r', encoding='utf-8') as f:
                html_content = f.read()
            
            # 替换占位符
            for key, value in kwargs.items():
                placeholder = f'{{{{{key}}}}}'
                html_content = html_content.replace(placeholder, str(value))
            
            return html_content
            
        except Exception as e:
            print(f"❌ 加载HTML模板失败: {e}")
            # 返回简单的错误页面
            return f"""
            <!DOCTYPE html>
            <html><head><title>Error</title></head>
            <body><h1>Template Error</h1><p>{str(e)}</p></body></html>
            """
    
    def log_message(self, format, *args):
        """重写日志方法，减少输出"""
        pass
    
    def do_GET(self):
        """处理GET请求"""
        try:
            # 解析URL
            parsed_url = urlparse(self.path)
            query_params = parse_qs(parsed_url.query)
            
            print(f"\n📥 收到回调请求: {self.path}")
            
            # 处理回调页面
            if parsed_url.path == '/callback' or parsed_url.path == '/fallback':
                self.handle_callback(query_params)
            else:
                self.handle_404()
                
        except Exception as e:
            print(f"❌ 处理请求时出错: {e}")
            self.send_error(500, f"Internal Server Error: {str(e)}")
    
    def handle_callback(self, query_params):
        """处理授权回调"""
        # 提取授权码和状态
        code = query_params.get('code', [None])[0]
        state = query_params.get('state', [None])[0]
        error = query_params.get('error', [None])[0]
        
        if error:
            print(f"❌ 授权失败: {error}")
            self.send_error_page(f"授权失败: {error}")
            return
        
        if code:
            print(f"✅ 成功获取授权码: {code[:10]}...{code[-10:]}")
            
            # 保存授权码到类变量
            FallbackHandler.auth_code = code
            FallbackHandler.auth_state = state
            
            # 尝试自动交换令牌
            success = self.exchange_token_automatically(code)
            
            # 发送成功页面
            self.send_success_page(code, success)
            
            # 设置服务器停止标志
            FallbackHandler.server_should_stop = True
            
        else:
            print("❌ 未找到授权码")
            self.send_error_page("未找到授权码")
    
    def exchange_token_automatically(self, auth_code):
        """自动交换访问令牌"""
        try:
            config = Config()
            client = FeishuBitableClient(config.CLIENT_ID, config.CLIENT_SECRET, config.REDIRECT_URI)
            
            print(f"\n🔄 正在自动交换访问令牌...")
            success = client.exchange_code_for_tokens(auth_code)
            
            if success:
                print("✅ 成功获取访问令牌！")
                
                # 显示令牌信息
                tokens = client.token_storage.load_tokens()
                if tokens:
                    print(f"\n📋 令牌信息:")
                    print(f"   访问令牌: {tokens.get('access_token', 'N/A')[:20]}...")
                    print(f"   权限范围: {tokens.get('scope', 'N/A')}")
                    print(f"   有效期: {tokens.get('expires_in', 'N/A')} 秒")
                
                return True
            else:
                print("❌ 获取访问令牌失败")
                return False
                
        except Exception as e:
            print(f"❌ 自动交换令牌时出错: {e}")
            return False
    
    def send_success_page(self, code, token_success):
        """发送成功页面"""
        html_content = self.get_success_html(code, token_success)
        
        self.send_response(200)
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.send_header('Content-Length', str(len(html_content.encode('utf-8'))))
        self.end_headers()
        self.wfile.write(html_content.encode('utf-8'))
    
    def send_error_page(self, error_message):
        """发送错误页面"""
        html_content = self.get_error_html(error_message)
        
        self.send_response(400)
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.send_header('Content-Length', str(len(html_content.encode('utf-8'))))
        self.end_headers()
        self.wfile.write(html_content.encode('utf-8'))
    
    def handle_404(self):
        """处理404错误"""
        html_content = self.get_404_html()
        
        self.send_response(404)
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.send_header('Content-Length', str(len(html_content.encode('utf-8'))))
        self.end_headers()
        self.wfile.write(html_content.encode('utf-8'))
    
    def get_success_html(self, code, token_success):
        """生成成功页面HTML"""
        token_status = "✅ 访问令牌获取成功" if token_success else "⚠️ 访问令牌获取失败"
        token_color = "#28a745" if token_success else "#ffc107"
        
        return self.load_html_template(
            'success',
            AUTH_CODE_DISPLAY=f"{code[:15]}...{code[-10:]}",
            CURRENT_TIME=time.strftime('%Y-%m-%d %H:%M:%S'),
            TOKEN_STATUS=token_status,
            TOKEN_COLOR=token_color,
            FULL_AUTH_CODE=code
        )
    
    def get_error_html(self, error_message):
        """生成错误页面HTML"""
        return self.load_html_template('error', ERROR_MESSAGE=error_message)
    
    def get_404_html(self):
        """生成404页面HTML"""
        return self.load_html_template('404')


class FallbackServer:
    """飞书授权回调服务器"""
    
    def __init__(self, port=8080, host='localhost'):
        self.port = port
        self.host = host
        self.server = None
        self.server_thread = None
    
    def start(self, timeout=300, auto_stop=True):
        """启动服务器
        
        Args:
            timeout: 超时时间（秒），默认5分钟
            auto_stop: 获取授权码后是否自动停止服务器，默认True
        
        Returns:
            str: 获取到的授权码，如果超时或失败返回None
        """
        try:
            # 重置状态
            FallbackHandler.auth_code = None
            FallbackHandler.auth_state = None
            FallbackHandler.server_should_stop = False
            
            # 创建服务器
            self.server = ThreadingHTTPServer((self.host, self.port), FallbackHandler)
            
            print(f"\n🚀 启动授权回调服务器...")
            print(f"   地址: http://{self.host}:{self.port}")
            print(f"   回调地址: http://{self.host}:{self.port}/callback")
            print(f"   备用地址: http://{self.host}:{self.port}/fallback")
            print(f"   超时时间: {timeout} 秒")
            print(f"   自动停止: {'是' if auto_stop else '否'}")
            
            # 在新线程中启动服务器
            self.server_thread = threading.Thread(target=self._run_server)
            self.server_thread.daemon = True
            self.server_thread.start()
            
            print(f"\n⏳ 等待授权回调...")
            
            # 等待授权码或超时
            start_time = time.time()
            while time.time() - start_time < timeout:
                if FallbackHandler.auth_code:
                    print(f"\n✅ 成功获取授权码: {FallbackHandler.auth_code[:10]}...{FallbackHandler.auth_code[-10:]}")
                    
                    if auto_stop:
                        # 等待一段时间让用户看到成功页面，然后停止服务器
                        print(f"\n⏳ 等待5秒让用户查看成功页面...")
                        time.sleep(5)
                        self.stop()
                    else:
                        print(f"\n🔄 服务器将继续运行，可以处理更多回调请求")
                        print(f"   如需停止服务器，请按 Ctrl+C")
                    
                    return FallbackHandler.auth_code
                
                if FallbackHandler.server_should_stop:
                    break
                
                time.sleep(0.5)
            
            print(f"\n⏰ 等待超时，未收到授权回调")
            if auto_stop:
                self.stop()
            return None
            
        except Exception as e:
            print(f"❌ 启动服务器失败: {e}")
            if auto_stop:
                self.stop()
            return None
    
    def _run_server(self):
        """运行服务器"""
        try:
            self.server.serve_forever()
        except Exception as e:
            if not FallbackHandler.server_should_stop:
                print(f"❌ 服务器运行出错: {e}")
    
    def stop(self):
        """停止服务器"""
        if self.server:
            try:
                self.server.shutdown()
                self.server.server_close()
                print(f"\n🛑 授权回调服务器已停止")
            except Exception as e:
                print(f"❌ 停止服务器时出错: {e}")
    
    def get_auth_code(self):
        """获取授权码"""
        return FallbackHandler.auth_code
    
    def start_persistent(self, port=None):
        """启动持续运行的服务器（不会自动停止）
        
        Args:
            port: 端口号，如果不指定则使用初始化时的端口
        """
        if port:
            self.port = port
            
        try:
            # 重置状态
            FallbackHandler.auth_code = None
            FallbackHandler.auth_state = None
            FallbackHandler.server_should_stop = False
            
            # 创建服务器
            self.server = ThreadingHTTPServer((self.host, self.port), FallbackHandler)
            
            print(f"\n🚀 启动持续运行的授权回调服务器...")
            print(f"   地址: http://{self.host}:{self.port}")
            print(f"   回调地址: http://{self.host}:{self.port}/callback")
            print(f"   备用地址: http://{self.host}:{self.port}/fallback")
            print(f"   模式: 持续运行（不会自动停止）")
            print(f"   停止方式: 按 Ctrl+C 或调用 stop() 方法")
            
            print(f"\n⏳ 等待授权回调...")
            print(f"   服务器将持续运行，可以处理多次授权请求")
            
            # 直接运行服务器（阻塞模式）
            self.server.serve_forever()
            
        except KeyboardInterrupt:
            print(f"\n\n👋 用户中断，正在停止服务器...")
            self.stop()
        except Exception as e:
            print(f"❌ 启动服务器失败: {e}")
            self.stop()


def main():
    """主函数 - 用于测试服务器"""
    print("🚀 飞书授权回调服务器")
    print("\n此服务器用于处理飞书OAuth授权回调")
    
    try:
        # 从配置获取端口
        config = Config()
        port = getattr(config, 'CALLBACK_PORT', 8080)
        
        print("\n请选择运行模式:")
        print("1. 单次授权模式（获取授权码后自动停止）")
        print("2. 持续运行模式（可处理多次授权，手动停止）")
        
        while True:
            choice = input("\n请选择 (1-2): ").strip()
            
            if choice == '1':
                # 单次授权模式
                print(f"\n🔄 启动单次授权模式...")
                server = FallbackServer(port=port)
                auth_code = server.start(timeout=300, auto_stop=True)  # 5分钟超时，自动停止
                
                if auth_code:
                    print(f"\n🎉 授权流程完成！")
                    print(f"   授权码: {auth_code}")
                    print(f"\n✅ 现在您可以使用以下方式运行示例:")
                    print(f"   python run_example.py")
                    print(f"   python goods_manager.py")
                else:
                    print(f"\n❌ 未能获取授权码")
                    print(f"   请检查网络连接和授权流程")
                break
                
            elif choice == '2':
                # 持续运行模式
                print(f"\n🔄 启动持续运行模式...")
                print(f"   服务器将持续运行，可以处理多次授权请求")
                print(f"   按 Ctrl+C 停止服务器")
                
                server = FallbackServer(port=port)
                server.start_persistent()
                break
                
            else:
                print(f"❌ 无效选择，请输入1或2")
            
    except KeyboardInterrupt:
        print(f"\n\n👋 程序已退出")
    except Exception as e:
        print(f"\n❌ 程序运行失败: {e}")


if __name__ == '__main__':
    main()